package com.ellison.zookeeperdemo.lock2;

import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.exception.ZkException;

import java.util.concurrent.CountDownLatch;

/**
 * 分布式锁   独占锁实现
 * 特点：效率低下，watch同时通知所有剩下节点，耗费资源
 *
 * @Author Ellison Pei
 * @Date 2021/6/30 21:39
 **/
public class ZkLockImpl extends ZkAbstractLock {


    private CountDownLatch cdl = null;

    /**
     * 尝试获取锁：
     * 去根目录创建节点，成功返回true  失败返回 false
     *
     * @return
     */
    @Override
    protected boolean tryLock() {
        try {
            client.createEphemeral(path);
            return true;
        } catch (ZkException e) {
            return false;
        }
    }

    /**
     * lock等待，等到前面获取锁的客户释放锁以后；
     * //没有获取到锁的客户端都会走到这里
     * //1、没有获取到锁的要注册对/lock节点的watcher
     * //2、这个方法需要等待
     */
    @Override
    protected void waitForLock() {

        IZkDataListener iZkDataListener = new IZkDataListener() {

            @Override
            public void handleDataChange(String dataPath, Object data) throws Exception {

            }

            // 一但 lock节点被删除后  就会触发这个方法
            @Override
            public void handleDataDeleted(String dataPath) throws Exception {
                // 让等待的方法不再等待
                if (cdl != null) {
                    cdl.countDown();
                }
            }
        };
        //注册监听
        client.subscribeDataChanges(path, iZkDataListener);
        if (client.exists(path)) {
            cdl = new CountDownLatch(1);
            try {
                cdl.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        // 取消订阅关系
        client.unsubscribeDataChanges(path, iZkDataListener);
    }
}
